package com.techsoft.plugins;

import java.io.File;
import java.io.FilenameFilter;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class PluginClassLoader extends URLClassLoader {
	private static Logger Log = LoggerFactory
			.getLogger(PluginClassLoader.class);
	private List<JarURLConnection> cachedJarFiles = new ArrayList<JarURLConnection>();

	public PluginClassLoader(ClassLoader parent) {
		super(new URL[] {}, parent);
	}

	public void addURLFile(URL file) {
		try {
			// open and cache JAR file connection
			URLConnection uc = file.openConnection();
			if (uc instanceof JarURLConnection) {
				uc.setUseCaches(true);
				((JarURLConnection) uc).getManifest();
				cachedJarFiles.add((JarURLConnection) uc);
			}
		} catch (Exception e) {
			Log.warn("Failed to cache plugin JAR file: "
					+ file.toExternalForm());
		}
		addURL(file);
	}

	public void addDirectory(File directory) {
		try {
			if (directory.exists()) {
				File classes = new File(directory, "classes");
				this.addURL(classes.toURI().toURL());
			}

			File libDir = new File(directory, "lib");
			if (libDir.exists()) {
				File[] jars = libDir.listFiles(new FilenameFilter() {
					@Override
					public boolean accept(File dir, String name) {
						return name.endsWith(".jar");
					}
				});

				if (jars != null) {
					for (int i = 0; i < jars.length; i++) {
						if (jars[i] != null && jars[i].isFile()) {
							String jarFileUri = jars[i].toURI().toString()
									+ "!/";
							addURLFile(new URL("jar", "", -1, jarFileUri));
						}
					}
				}
			}
		} catch (MalformedURLException e) {
			Log.error(e.getMessage(), e);
		}
	}

	public void unloadJarFiles() {
		for (JarURLConnection url : cachedJarFiles) {
			try {
				Log.info("Unloading plugin JAR file "
						+ url.getJarFile().getName());
				url.getJarFile().close();
			} catch (Exception e) {
				Log.error("Failed to unload JAR file", e);
			}
		}
	}
}
